home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 2: CDPD 1
/
Almathera Ten on Ten - Disc 2: CDPD 1.iso
/
pd
/
301-325
/
325
/
keymacro
/
keymacro-handler.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-14
|
11KB
|
595 lines
#include "KeyMacro.h"
struct MXMBase *MXMBase;
struct IntuitionBase *IntuitionBase;
struct MSeg *MSeg;
LONG MSignal = -1;
struct KeyEquivalent *EquList;
struct Process *ExecuteProc;
struct MsgPort *ExecutePort;
struct MsgPort *InputDevPort;
struct IOStdReq *InputRequestBlock;
struct Interrupt HandlerStuff;
long ConsoleDevice = NULL;
struct IOStdReq ConStdReq;
/* FreeString(Byte):
*
* Frees the memory occupied by the contents of a BSTR.
*/
void
FreeString(Byte)
BPTR Byte;
{
long *Ptr = (long *)BADDR(Byte);
FreeMem(Ptr - 1,Ptr[-1]);
}
/* CreateBSTR(s):
*
* Allocates enough memory to hold the contents of
* a given string and makes it a BSTR.
*/
BPTR
CreateBSTR(s)
char *s;
{
long Length = strlen(s);
long BlockLength = (Length + 8) & ~3;
char *Byte;
if(!(Byte = (char *)AllocMem(BlockLength,MEMF_PUBLIC | MEMF_CLEAR)))
return(NULL);
*(long *)Byte = BlockLength;
Byte[4] = Length;
strncpy(Byte + 5,s,Length);
return((long)(Byte + 4) >> 2);
}
/* CopyPath():
*
* Builds a fake pathlist inherited from any valid
* CLI process or Workbench.
*/
BPTR
CopyPath()
{
struct Process *Father;
struct CommandLineInterface *CLI;
BPTR *Next1,*Next2,*Last,NewPath = NULL;
Last = &NewPath;
/* If using ARP this will also give us a valid
* pathlist.
*/
if(!(Father = (struct Process *)FindTask("Workbench")))
if(!(Father = (struct Process *)FindTask("ARP Shell Process")))
if(!(Father = (struct Process *)FindTask("New CLI")))
if(!(Father = (struct Process *)FindTask("Initial CLI")))
return(NULL);
if(!(CLI = (struct CommandLineInterface *)BADDR(Father -> pr_CLI)))
return(NULL);
for(Next1 = (BPTR *)BADDR(CLI -> cli_CommandDir) ; Next1 ; Next1 = (BPTR *)BADDR(*Next1))
{
if(!(Next2 = (BPTR *)AllocMem(2 * sizeof(BPTR),MEMF_PUBLIC | MEMF_CLEAR)))
break;
*Last = (long)Next2 >> 2;
Last = Next2;
Next2[1] = (BPTR)DupLock(Next1[1]);
Next2[0] = NULL;
}
return(NewPath);
}
/* FakeCLI():
*
* Creates a fake CLI structure for out process. This
* includes pathlist, currentdir, prompt and stack.
*/
void
FakeCLI()
{
struct CommandLineInterface *CLI;
struct Process *MyProcess = (struct Process *)FindTask(NULL);
if(!(CLI = (struct CommandLineInterface *)AllocMem(sizeof(struct CommandLineInterface),MEMF_PUBLIC | MEMF_CLEAR)))
return;
MyProcess -> pr_CLI = (long)CLI >> 2;
CLI -> cli_SetName = CreateBSTR("SYS:");
CLI -> cli_Prompt = CreateBSTR("%N> ");
CLI -> cli_DefaultStack = 4000;
CurrentDir(Lock("SYS:",ACCESS_READ));
CLI -> cli_CommandDir = CopyPath();
}
/* ClearPath(InitPath):
*
* Frees the contents of our fake pathlist.
*/
void
ClearPath(InitPath)
BPTR InitPath;
{
BPTR *Next,*Path;
for(Path = (BPTR *)BADDR(InitPath) ; Path ; Path = Next)
{
Next = (BPTR *)BADDR(Path[0]);
if(Path[1])
UnLock(Path[1]);
FreeMem(Path,2 * sizeof(BPTR));
}
}
/* StopFakery():
*
* Removes the contents of our fake CLI structure.
*/
void
StopFakery()
{
BPTR MyCD = (BPTR)CurrentDir(NULL);
struct Process *MyProcess = (struct Process *)FindTask(NULL);
struct CommandLineInterface *CLI = (struct CommandLineInterface *)BADDR(MyProcess -> pr_CLI);
if(!CLI)
return;
if(MyCD)
UnLock(MyCD);
FreeString(CLI -> cli_SetName);
FreeString(CLI -> cli_Prompt);
ClearPath(CLI -> cli_CommandDir);
MyProcess -> pr_CLI = NULL;
FreeMem(CLI,sizeof(struct CommandLineInterface));
}
void *
DeleteCustomMsg(scm_Msg)
struct MacroMessage *scm_Msg;
{
if(scm_Msg && scm_Msg -> mm_Message . mn_Node . ln_Name == scm_Msg)
FreeRem(scm_Msg);
return(NULL);
}
void *
SendCustomMsg(scm_Msg,scm_Port)
struct MacroMessage *scm_Msg;
struct MsgPort *scm_Port;
{
struct MacroMessage *scm_TempMsg = (struct MacroMessage *)AllocRem(sizeof(struct MacroMessage),MEMF_PUBLIC | MEMF_CLEAR);
if(scm_TempMsg)
{
CopyMem(scm_Msg,scm_TempMsg,sizeof(struct MacroMessage));
scm_TempMsg -> mm_Message . mn_Node . ln_Name = (char *)scm_TempMsg;
scm_TempMsg -> mm_Message . mn_ReplyPort = NULL;
scm_TempMsg -> mm_Message . mn_Length = sizeof(struct MacroMessage);
PutMsg(scm_Port,scm_TempMsg);
}
return((void *)scm_TempMsg);
}
void
Executor()
{
ULONG SignalSet,NilHandle;
struct MacroMessage *ExecuteMsg;
struct Window *TheWindow;
geta4();
if(!(ExecutePort = (struct MsgPort *)CreatePort(NULL,0)))
return;
if(!(NilHandle = (ULONG)Open("NIL:",MODE_NEWFILE)))
{
DeletePort(ExecutePort);
return;
}
FakeCLI();
FOREVER
{
SignalSet = Wait(SIG_CLOSE | (1 << ExecutePort -> mp_SigBit));
if(SignalSet & SIG_CLOSE)
{
StopFakery();
Close(NilHandle);
DeletePort(ExecutePort);
ExecuteProc = NULL;
return;
}
while(ExecuteMsg = (struct MacroMessage *)GetMsg(ExecutePort))
{
TheWindow = NULL;
if(ExecuteMsg -> mm_WindowName)
{
ULONG IntuiLock;
struct Screen *ExScreen;
struct Window *ExWindow;
IntuiLock = LockIBase(NULL);
ExScreen = IntuitionBase -> FirstScreen;
do
{
ExWindow = ExScreen -> FirstWindow;
do
{
if(!UStrCmp(ExecuteMsg -> mm_WindowName,ExWindow -> Title))
{
UnlockIBase(IntuiLock);
TheWindow = ExWindow;
goto SkipLoop;
}
}
while(ExWindow = ExWindow -> NextWindow);
}
while(ExScreen = ExScreen -> NextScreen);
UnlockIBase(IntuiLock);
}
Execute(ExecuteMsg -> mm_FileName,NULL,NilHandle);
SkipLoop: DeleteCustomMsg(ExecuteMsg);
if(TheWindow)
{
WindowToFront(TheWindow);
ScreenToFront(TheWindow -> WScreen);
ActivateWindow(TheWindow);
}
}
}
}
struct MacroKey *
FindMacroKey(Code,Qualifier)
LONG Code,Qualifier;
{
long i;
if(!MSeg -> MacroList)
return(NULL);
for(i = 0 ; i < MSeg -> NumMacros ; i++)
{
if(MSeg -> MacroList[i] . mk_Type == MK_UNUSED)
continue;
if(MSeg -> MacroList[i] . mk_CommandKey == Code && (Qualifier & MSeg -> MacroList[i] . mk_CommandQualifier) == MSeg -> MacroList[i] . mk_CommandQualifier)
return(&MSeg -> MacroList[i]);
}
return(NULL);
}
#asm
_Handler: MOVEM.L A4,-(A7)
MOVEM.L A0/A1,-(A7)
JSR _geta4#
JSR _EventHandler
ADDQ.L #8,A7
MOVEM.L (A7)+,A4
RTS
#endasm
struct InputEvent *
EventHandler(Event)
struct InputEvent *Event;
{
register struct MacroKey *HandlerKey;
if(Event -> ie_Class != IECLASS_RAWKEY || Event -> ie_Code & IECODE_UP_PREFIX)
return(Event);
if(HandlerKey = (struct MacroKey *)FindMacroKey(Event -> ie_Code,Event -> ie_Qualifier))
{
struct MacroMessage HandlerMsg;
HandlerMsg . mm_Type = MM_INPUT;
HandlerMsg . mm_MacroKey= HandlerKey;
SendCustomMsg(&HandlerMsg,&MSeg -> Port);
Event -> ie_Class = IECLASS_NULL;
}
return(Event);
}
BOOL
InitHandler()
{
extern void Handler();
if(OpenDevice("console.device",-1,&ConStdReq,0))
return(FALSE);
ConsoleDevice = (long)ConStdReq . io_Device;
if(!(InputDevPort = (struct MsgPort *)CreatePort(NULL,0)))
return(FALSE);
if(!(InputRequestBlock = (struct IOStdReq *)CreateStdIO(InputDevPort)))
return(FALSE);
if(OpenDevice("input.device",0,InputRequestBlock,0))
return(FALSE);
HandlerStuff . is_Code = Handler;
HandlerStuff . is_Node . ln_Pri = 60;
HandlerStuff . is_Node . ln_Name= "KeyMacro-Handler";
InputRequestBlock -> io_Command = IND_ADDHANDLER;
InputRequestBlock -> io_Data = (APTR)&HandlerStuff;
DoIO(InputRequestBlock);
return(TRUE);
}
void
FlushHandler()
{
if(ConsoleDevice)
CloseDevice(&ConStdReq);
if(InputRequestBlock -> io_Device)
{
InputRequestBlock -> io_Command = IND_REMHANDLER;
InputRequestBlock -> io_Data = (APTR)&HandlerStuff;
DoIO(InputRequestBlock);
CloseDevice(InputRequestBlock);
}
if(InputRequestBlock)
DeleteStdIO(InputRequestBlock);
if(InputDevPort)
DeletePort(InputDevPort);
}
void
ShutDown()
{
FlushHandler();
if(ExecuteProc)
{
Signal(ExecuteProc,SIG_CLOSE);
while(ExecuteProc)
Delay(10);
}
if(MXMBase)
CloseLibrary(MXMBase);
if(MSignal != -1)
FreeSignal(MSignal);
Forbid();
if(MSeg -> Father)
Signal(MSeg -> Father,SIG_CLOSE);
if(!MSeg -> Father)
{
register BPTR Segment = MSeg -> Segment;
RemPort(&MSeg -> Port);
FreeMem(MSeg -> Port . mp_Node . ln_Name,sizeof(PORTNAME));
UnLoadSeg(Segment);
Wait(NULL);
}
}
long
_main()
{
struct Process *ThatsMe = (struct Process *)FindTask(NULL);
ULONG SignalSet;
struct MacroMessage *MacroMsg;
register long i;
if(ThatsMe -> pr_CLI)
return(10);
if(!(MSeg = (struct MSeg *)FindPort(PORTNAME)))
return(10);
if(MSeg -> Port . mp_Flags == PA_SIGNAL)
return(10);
if(MSeg -> Revision < REVISION)
{
Signal(MSeg -> Father,MSeg -> RingBack);
return(10);
}
if(!InitHandler())
{
FlushHandler();
Signal(MSeg -> Father,MSeg -> RingBack);
return(20);
}
if(!(MXMBase = (struct MXMBase *)OpenLibrary("mxm.library",0)))
{
FlushHandler();
Signal(MSeg -> Father,MSeg -> RingBack);
return(20);
}
IntuitionBase = (struct IntuitionBase *)MXMBase -> IntuitionBase;
if((MSignal = AllocSignal(-1)) == -1)
{
CloseLibrary(MXMBase);
FlushHandler();
Signal(MSeg -> Father,MSeg -> RingBack);
return(20);
}
if(!(ExecuteProc = (struct Process *)CreateFuncProc("KeyMacro.exec",10,Executor,4000)))
{
FreeSignal(MSignal);
CloseLibrary(MXMBase);
FlushHandler();
Signal(MSeg -> Father,MSeg -> RingBack);
return(20);
}
MSeg -> Child = (struct Task *)ThatsMe;
Signal(MSeg -> Father,MSeg -> RingBack);
MSeg -> Father = NULL;
MSeg -> Port . mp_Flags = PA_SIGNAL;
MSeg -> Port . mp_SigBit = MSignal;
MSeg -> Port . mp_SigTask = MSeg -> Child;
FOREVER
{
SignalSet = Wait(SIG_CLOSE | SIG_PORT);
if(SignalSet & SIG_CLOSE)
{
ShutDown();
return(0);
}
if(SignalSet & SIG_PORT)
{
while(MacroMsg = (struct MacroMessage *)GetMsg(&MSeg -> Port))
{
if(MacroMsg -> mm_Type == MM_INPUT)
{
struct MacroKey *TempMacroKey = MacroMsg -> mm_MacroKey;
if(TempMacroKey)
{
if(TempMacroKey -> mk_Type == MK_COMMAND)
{
struct MacroMessage CommandMsg;
CommandMsg . mm_Type = MM_EXECUTE;
CommandMsg . mm_FileName = TempMacroKey -> mk_String;
CommandMsg . mm_WindowName = TempMacroKey -> mk_Window;
SendCustomMsg(&CommandMsg,ExecutePort);
}
if(TempMacroKey -> mk_Type == MK_WORD)
{
struct InputEvent FakeInputEvent;
InputRequestBlock -> io_Command = IND_WRITEEVENT;
InputRequestBlock -> io_Data = (APTR)&FakeInputEvent;
setmem(&FakeInputEvent,sizeof(struct InputEvent),0);
FakeInputEvent . ie_Class = IECLASS_RAWKEY;
for(i = 0 ; i < strlen(TempMacroKey -> mk_String) ; i++)
if(InvertKey(TempMacroKey -> mk_String[i],&FakeInputEvent,IK_USEIKM,NULL))
DoIO(InputRequestBlock);
}
}
}
if(MacroMsg -> mm_Type == MM_UPDATE)
{
if(MSeg -> MacroList)
{
for(i = 0 ; i < MSeg -> NumMacros ; i++)
{
if(MSeg -> MacroList[i] . mk_Type == MK_UNUSED)
continue;
if(MSeg -> MacroList[i] . mk_String)
FreeRem(MSeg -> MacroList[i] . mk_String);
if(MSeg -> MacroList[i] . mk_Window)
FreeRem(MSeg -> MacroList[i] . mk_Window);
}
FreeRem(MSeg -> MacroList);
}
MSeg -> NumMacros = MacroMsg -> mm_NumMacros;
MSeg -> MacroList = MacroMsg -> mm_MacroList;
}
DeleteCustomMsg(MacroMsg);
}
}
}
}